package com.yoosora.plugins.aop;

import com.alibaba.fastjson.JSON;
import com.mikuac.shiro.annotation.MessageHandler;
import com.mikuac.shiro.common.utils.MsgUtils;
import com.mikuac.shiro.common.utils.RegexUtils;
import com.mikuac.shiro.core.Bot;
import com.mikuac.shiro.core.BotPlugin;
import com.mikuac.shiro.dto.event.message.GroupMessageEvent;
import com.mikuac.shiro.dto.event.message.WholeMessageEvent;
import com.yoosora.common.consts.ConstsI;
import com.yoosora.common.mode.request.plugin.PluginOtherRequest;
import com.yoosora.common.mode.request.plugin.PluginSaveRequest;
import com.yoosora.common.mode.response.MultiResponse;
import com.yoosora.common.mode.response.SingleResponse;
import com.yoosora.model.PluginDTO;
import com.yoosora.service.PluginService;
import com.yoosora.utils.RegexConst;
import com.yoosora.utils.Strings;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Aspect
@Component
public class AuthPlugin extends BotPlugin {
	
	private final String PLUGIN = "ACTIVE_PLUGIN";
	
	@Autowired
	private RedisTemplate<String,String> redisTemplate;
	
	private static StringBuilder sb  = new StringBuilder();
	
	@Autowired
	private PluginService pluginService;
	
	private Map<String,String> nameMap;
	
	private Set<String> nameSet;
	
	@PostConstruct
	public void init(){
		PluginOtherRequest request = new PluginOtherRequest();
		MultiResponse<PluginDTO> response = pluginService.queryList(request);
		nameMap = response.getList().stream().collect(Collectors.toMap(PluginDTO::getName, PluginDTO::getPackageName));
		nameSet = nameMap.keySet();
		List<String> activePlugin = getActive();
		redisTemplate.opsForValue().set(PLUGIN, JSON.toJSONString(activePlugin));
	}
	
	@MessageHandler(cmd = RegexConst.PLUGIN_ENABLE)
	public void enablePlugin(@NotNull Bot bot, @NotNull WholeMessageEvent event){
		String msg = event.getMessage();
		GroupMessageEvent.GroupSender sender = event.getSender();
		if("1592184684".equals(sender.getUserId())){
			String pluginName = RegexUtils.regexGroup(RegexConst.PLUGIN_ENABLE, msg, 1);
			if(null!=pluginName&& Strings.isNotEmpty(pluginName)){
				if(nameSet.contains(pluginName)){
					PluginOtherRequest pluginOtherRequest = new PluginOtherRequest();
					pluginOtherRequest.setPackageName(nameMap.get(pluginName));
					MultiResponse<PluginDTO> pluginDTOMultiResponse = pluginService.queryList(pluginOtherRequest);
					PluginDTO pluginDTO = pluginDTOMultiResponse.getList().get(0);
					PluginSaveRequest save = new PluginSaveRequest();
					save.setId(pluginDTO.getId());
					save.setIsActive(ConstsI.ONE);
					SingleResponse<Long> saveresponse = pluginService.save(save);
					if(null!=saveresponse.getObj()){
						sb.append(pluginName).append("启用成功");
					}else{
						sb.append(pluginName).append("启用失败,请检查数据库配置");
					}
				}else{
					sb.append("插件不存在");
				}
			}else{
				sb.append("请以 [插件名]插件启用 格式，启用插件");
			}
		}else{
			sb.append("权限不足");
		}
		List<String> activePlugin = getActive();
		redisTemplate.opsForValue().set(PLUGIN, JSON.toJSONString(activePlugin));
		bot.sendMsg(event, MsgUtils.builder().text(sb.toString()).build(), false);
		sb.setLength(0);
	}
	
	@MessageHandler(cmd = RegexConst.PLUGIN_DISABLE)
	public void disablePlugin(@NotNull Bot bot,@NotNull WholeMessageEvent event){
		String msg = event.getMessage();
		GroupMessageEvent.GroupSender sender = event.getSender();
		if("1592184684".equals(sender.getUserId())) {
			String pluginName = RegexUtils.regexGroup(RegexConst.PLUGIN_DISABLE, msg, 1);
			if (null != pluginName && Strings.isNotEmpty(pluginName)) {
				if(nameSet.contains(pluginName)){
					PluginOtherRequest pluginOtherRequest = new PluginOtherRequest();
					pluginOtherRequest.setPackageName(nameMap.get(pluginName));
					MultiResponse<PluginDTO> pluginDTOMultiResponse = pluginService.queryList(pluginOtherRequest);
					PluginDTO pluginDTO = pluginDTOMultiResponse.getList().get(0);
					PluginSaveRequest save = new PluginSaveRequest();
					save.setId(pluginDTO.getId());
					save.setIsActive(ConstsI.ZERO);
					SingleResponse<Long> saveresponse = pluginService.save(save);
					if(null!=saveresponse.getObj()){
						sb.append(pluginName).append("禁用成功");
					}else{
						sb.append(pluginName).append("禁用失败,请检查数据库配置");
					}
				}else{
					sb.append("插件不存在");
				}
			} else {
				sb.append("请以 [插件名]插件禁用 格式，禁用插件");
			}
		}else{
			sb.append("权限不足");
		}
		List<String> activePlugin = getActive();
		redisTemplate.opsForValue().set(PLUGIN, JSON.toJSONString(activePlugin));
		bot.sendMsg(event, MsgUtils.builder().text(sb.toString()).build(), false);
		sb.setLength(0);
	}
	
	public List<String> getActive(){
		PluginOtherRequest request = new PluginOtherRequest();
		request.setIsActive(ConstsI.ONE);
		MultiResponse<PluginDTO> pluginDTOMultiResponse = pluginService.queryList(request);
		List<String> activePlugin = pluginDTOMultiResponse.getList().stream().map(PluginDTO::getPackageName).collect(Collectors.toList());
		return activePlugin;
	}
	
	@Pointcut("execution(public * com.yoosora.plugins.*.*Msg(..))")
	public void messageLog(){}
	
	@Around("messageLog()")
	public void messageAround(ProceedingJoinPoint joinPoint) throws Throwable{
		List<String> activePlugin = null;
		String pluginString = redisTemplate.opsForValue().get(PLUGIN);
		if(Strings.isEmpty(pluginString)){ 
			activePlugin = getActive();
			redisTemplate.opsForValue().set(PLUGIN, JSON.toJSONString(activePlugin));
		}else{
			activePlugin = JSON.parseArray(pluginString,String.class);
		}
		String name = joinPoint.getSignature().getDeclaringTypeName()+"." +joinPoint.getSignature().getName();
		if(activePlugin.contains(name)){
			Object result = joinPoint.proceed();
		}else{
			Bot bot = null;
			WholeMessageEvent event = null;
			Object[] args = joinPoint.getArgs();
			if(args[0] instanceof Bot){
				bot = (Bot)args[0];
			}
			if(args[1] instanceof WholeMessageEvent){
				event = (WholeMessageEvent)args[1];
			}
			if(null != bot && null != event&&!"com.yoosora.plugins.BiliPlugin.biliMsg".equals(name)){
				sb.append("插件未启用，请联系yoosora开启");
				bot.sendMsg(event, MsgUtils.builder().text(sb.toString()).build(), false);
			}
			log.info("插件未启用");
		}
		sb.setLength(0);
	}
}
